/**
 * 生成ID通用类. tonydon v1.2 2012.5.18
 */
package cn.txdnet.key;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import txdnet.util.DataUtil;
import txdnet.util.Logger;
import txdnet.util.coder.Md5;
import txdnet.util.coder.SHA;

/**
 * @author jetsum
 *
 */
public class GenId {
	// private static long n1 = 2157583649L; // 2147483648

	private static short n3 = 0;
	private final static long f2 = 1325347259000L; // 2012-01-01 00:00:59
	private static long c2 = System.currentTimeMillis();
	private static Lock lock = new ReentrantLock();
        private final static int m2 = 9;

 /*
  * 利用系统时间，时间对照生成序列ID,适合会员ID，低并发ID生成使用
  * @return long
  */
    public static long makeSid(){
        long newId;
        long id = 0L;
        lock.lock();
        newId = System.currentTimeMillis();
        try{
            if(newId == c2){
                if(n3<m2){
                    n3++;
                    id = (newId - f2) * 10 + n3;
                }else{
                    n3 = 0;
                    TimeUnit.MILLISECONDS.sleep(16);
                    newId = System.currentTimeMillis();
                    id = (newId - f2)  * 10 ;
                }
            }else{
            n3=0;
            id = (newId - f2) * 10 ;
            }
            c2 = newId; // 更新参照ID
           }catch(Exception e){
            Logger.error(GenId.class, e.toString());
            id = -1L;
           }finally{
           lock.unlock();
           }
    return id;
    }
    

    /*
     * 随机生成字符串,使用Def.MAP1的CHAR表(MAP1是数字下划线和大小写字母, MAP2只有大小写字母)
     * @return String
     */
    public static String makeRndChr(int len){
        return GenId.makeRndChr(len, Def.MAP1);
    }
    
    public static String makeRndChr(int len, char[] map){
         StringBuilder sb = new StringBuilder(len);
        for(int k=0; k<len; k++){
                sb.append(map[DataUtil.genRndInt(0, map.length)]);
            }
        return sb.toString();
    }
    
    /*
     * 生成UUID，利用java.util.UUID+4个随机字符然后经过SHA HASH得到 40 位字符串序列，适合非数字ID的生成环境
     * 如SESSIONID，单号等
     * @return String
     */
    public static String makeUUID(){
        return GenId.makeUUID(4, SHA.SHA_1);
    }
    
    public static String makeUUID(int rnd_char_num, String sha_flag){
        return SHA.encode(UUID.randomUUID().toString().concat(GenId.makeRndChr(rnd_char_num)), sha_flag);
    }
    
/*
 * 短字串生成,输入一个字符串计算他的短字符串序列,返回 4组 6位HASH字串
 * @return String
 */
    public static String makeShortChar(String str){
        if(DataUtil.checkNull(str, null)==null) {
            return null;
        }
        String str_hex = Md5.encode(str);
        long hexint;
        StringBuilder sb = new StringBuilder();
        String tmp;
        for(int i=0; i<4; i++){//分4组
             tmp =   str_hex.substring(i*8, (i+1)*8) ;
            //  这里使用 long 型来转换， Inteper .parseInt() 只能处理 31 位 , 
             hexint =  0x3fffffff & Long.parseLong(tmp, 16);
             for  ( int  j = 0; j < 6; j++)  
            {  
                //把得到的值与字符表字符个数进行位与运算，取得字符数组MAP CHAR 索引  
                //把取得的字符相加   
                sb.append(Def.MAP1[ (int)((Def.MAP1.length-1) & hexint) ]);  
                //每次循环按位右移5位   
                hexint = hexint >> 5;  
            }  
              sb.append(" ");
         }
       return sb.toString();
    }
//
//    public static void main(String... arg) throws Exception{
//       System.out.println(GenId.makeSid());
//       System.out.println(GenId.makeRndChr(8).concat(GenId.makeUUID()).concat("!").concat(Long.toString(DataUtil.getMs(),16)));
//    }
}